#ifndef __WAV_PARSER_H
#define __WAV_PARSER_H

#include <QObject>

#include <stdio.h>
#include <malloc.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <fcntl.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <time.h>
#include <locale.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#ifdef Q_OS_UNIX
#include <alsa/asoundlib.h>
#endif
#include <assert.h>

typedef unsigned char  uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int   uint32_t;

#if __BYTE_ORDER == __LITTLE_ENDIAN
#define COMPOSE_ID(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
#define LE_SHORT(v)           (v)
#define LE_INT(v)               (v)
#define BE_SHORT(v)           bswap_16(v)
#define BE_INT(v)               bswap_32(v)
#elif __BYTE_ORDER == __BIG_ENDIAN
#define COMPOSE_ID(a,b,c,d) ((d) | ((c)<<8) | ((b)<<16) | ((a)<<24))
#define LE_SHORT(v)           bswap_16(v)
#define LE_INT(v)               bswap_32(v)
#define BE_SHORT(v)           (v)
#define BE_INT(v)               (v)
#else
#error "Wrong endian"
#endif

#define WAV_RIFF        COMPOSE_ID('R','I','F','F')
#define WAV_WAVE        COMPOSE_ID('W','A','V','E')
#define WAV_FMT         COMPOSE_ID('f','m','t',' ')
#define WAV_DATA        COMPOSE_ID('d','a','t','a')

/* WAVE fmt block constants from Microsoft mmreg.h header */
#define WAV_FMT_PCM             0x0001
#define WAV_FMT_IEEE_FLOAT      0x0003
#define WAV_FMT_DOLBY_AC3_SPDIF 0x0092
#define WAV_FMT_EXTENSIBLE      0xfffe

/* Used with WAV_FMT_EXTENSIBLE format */
#define WAV_GUID_TAG "/x00/x00/x00/x00/x10/x00/x80/x00/x00/xAA/x00/x38/x9B/x71"

/* it's in chunks like .voc and AMIGA iff, but my source say there
   are in only in this combination, so I combined them in one header;
   it works on all WAVE-file I have
 */
typedef struct WAVHeader {
    uint32_t magic;     /* 'RIFF' */
    uint32_t length;        /* filelen */
    uint32_t type;      /* 'WAVE' */
} WAVHeader_t;

typedef struct WAVFmt {
    uint32_t magic;  /* 'FMT '*/
    uint32_t fmt_size; /* 16 or 18 */
    uint16_t format;        /* see WAV_FMT_* */
    uint16_t channels;
    uint32_t sample_rate;   /* frequence of sample */
    uint32_t bytes_p_second;
    uint16_t blocks_align;  /* samplesize; 1 or 2 bytes */
    uint16_t sample_length; /* 8, 12 or 16 bit */
} WAVFmt_t;

typedef struct WAVFmtExtensible {
    WAVFmt_t format;
    uint16_t ext_size;
    uint16_t bit_p_spl;
    uint32_t channel_mask;
    uint16_t guid_format;   /* WAV_FMT_* */
    uint8_t guid_tag[14];   /* WAV_GUID_TAG */
} WAVFmtExtensible_t;

typedef struct WAVChunkHeader {
    uint32_t type;      /* 'data' */
    uint32_t length;        /* samplecount */
} WAVChunkHeader_t;

typedef struct WAVContainer {
    WAVHeader_t header;
    WAVFmt_t format;
    WAVChunkHeader_t chunk;
} WAVContainer_t;

class WavParser : public QObject {
    Q_OBJECT
public:
    explicit WavParser(QObject *parent = 0);

    int   WAV_ReadHeader(int fd, WAVContainer_t *container);
    int   WAV_WriteHeader(int fd, WAVContainer_t *container);
    char *WAV_P_FmtString(uint16_t fmt);
    void  WAV_P_PrintHeader(WAVContainer_t *container);
    int   WAV_P_CheckValid(WAVContainer_t *container);
};
#endif /* #ifndef __WAV_PARSER_H */
